package com.namecard.namecardapi.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.namecard.namecardapi.config.CommonConfig;
import com.namecard.namecardapi.entity.*;
import com.namecard.namecardapi.entity.DTO.OrderDTO;
import com.namecard.namecardapi.entity.emums.PaymentEnum;
import com.namecard.namecardapi.entity.vo.*;
import com.namecard.namecardapi.exception.BusinessException;
import com.namecard.namecardapi.mapper.*;
import com.namecard.namecardapi.service.OrderInfoService;
import com.namecard.namecardapi.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wzx
 * @since 2023-07-03
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Resource
    OrderInfoMapper orderInfoMapper;
    @Resource
    AccountInfoMapper accountInfoMapper;
    @Resource
    RfCommonPayLogMapper rfCommonPayLogMapper;
    @Resource
    CardOrderInfoMapper cardOrderInfoMapper;
    @Autowired
    OrderCardMapper orderCardMapper;
    @Autowired
    CardInfoMapper cardInfoMapper;
    @Resource
    SpecialOrderMapper specialOrderMapper;
    @Resource
    TagUtil tagUtil;
    @Autowired
    TagInfoMapper tagInfoMapper;
    @Resource
    private CommonConfig commonConfig;
    @Autowired
    private UserInfoMapper userInfoMapper;


    private static final String FALSE_PAY = "购买失败，请联系后台";

    private static final String APP_PHONE = "移动端";

    private static final String ORDER_BODY = "名片购买";

    private static final String TRADE_TYPE = "积分交易";

    private static final String GET_DATA_FALSE = "导出数据失败";

    private static final String SHEET = "pi数据表";
    @Override
    public void payOrderList(String cardIds, String userId, HttpServletRequest request) {
        // 拆解cardId数组
        String[] cardIdArray = cardIds.split(",");
        // 计算支付需要的积分总数
        BigDecimal needPoint = Constants.CARD_PRICE.multiply(BigDecimal.valueOf(cardIdArray.length));
        // 修改余额
        BigDecimal  pointBalance = updateAccountData(userId, needPoint);
        // 获取当前日期
        Date currentDate = new Date();
        // 支付成功，修改购物车中的商品状态
        long count = Arrays.stream(cardIdArray)
                .parallel()
                .peek(s -> {
                    // 创建Calendar对象并设置日期
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(currentDate);
                    // 将日期增加30天
                    calendar.add(Calendar.DAY_OF_MONTH, Constants.INVALID_TIME);
                    // 获取增加后的日期
                    Date newDate = calendar.getTime();
                    // 修改订单的状态为已支付状态
                    OrderInfo orderInfo = new OrderInfo(null, null, currentDate, currentDate, 0,
                            needPoint, null, newDate, 1, null, null);
                    int flag = orderInfoMapper.update(orderInfo, new QueryWrapper<OrderInfo>()
                                                                    .eq("user_id", userId)
                                                                    .eq("shop_id", s));
                    if (flag < 1) {
                        throw new BusinessException(FALSE_PAY);
                    }
                    int insert = saveRfCommonPayLog(userId, s, needPoint, pointBalance, request);
                    if (insert < 1) {
                        throw new BusinessException(FALSE_PAY);
                    }
                })
                .count();
        // 在用户已有的订单数据中插入该cardId
        CardOrderInfo cardOrderInfo = cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>().eq("user_id", userId).select("card_list"));
        String jsonString;
        if (cardOrderInfo == null) {
            List<String> listCardId = Arrays.asList(cardIdArray);
            jsonString = JSON.toJSONString(listCardId);

        }else {
            JSONArray list = JSON.parseArray(cardOrderInfo.getCardList());
            List<String> cardIdList = JSONObject.parseArray(list.toJSONString(), String.class);
            cardIdList.addAll(Arrays.asList(cardIdArray));
            long count1 = cardIdList.stream().distinct().count();
            // userIdList转为jsonString
            jsonString = JSON.toJSONString(cardIdList);
        }
        int update1 = cardOrderInfoMapper.update(null, new UpdateWrapper<CardOrderInfo>().eq("user_id", userId).set("card_list", jsonString));
        if (update1 < 1){throw new BusinessException(FALSE_PAY);}
    }


    @Override
    public List<OrderListFinalVO> getNoPayOrderList(String userId) {
        // 获取该用户的所有未支付的订单数据
        List<OrderListVO> noPayOrderList = orderInfoMapper.getNoPayOrderList(userId);
        return getResult(noPayOrderList);
    }

    @Override
    public List<OrderCardInfoVO> getPayOrderList(String userId) {
        List<OrderCardInfoVO> OrderCardInfoVOList = orderInfoMapper.getOrderList(userId);
        for (OrderCardInfoVO orderCardInfoVO : OrderCardInfoVOList) {
            String orderId = orderCardInfoVO.getOrderId();
            List<OrderCard> orderCardList = orderCardMapper.selectList(new QueryWrapper<OrderCard>()
                    .eq("order_id", orderId));
            List<String> user_id = orderCardList.stream().map(orderCard -> {
                String cardId = orderCard.getCardId();
                CardInfo cardInfo = cardInfoMapper.selectOne(new QueryWrapper<CardInfo>()
                        .eq("card_id", cardId));
                if (cardInfo == null) {return null;}
                return cardInfo.getUserId();
            }).collect(Collectors.toList());
            List<String> images = user_id.stream().map(id -> {
                UserInfo userInfo = userInfoMapper.selectOne(new QueryWrapper<UserInfo>()
                        .eq("user_id", id));
                if (userInfo == null) {return null;}
                return "/img/avatar/" + userInfo.getUserImage() + ".jpg";
            }).collect(Collectors.toList());
            orderCardInfoVO.setUserImage(images);
        }
        return OrderCardInfoVOList;
    }

    @Override
    public boolean saveOrderCardCar(String shopUserId, String shopId, String userId) {
        // 构造函数
        OrderInfo orderInfo = new OrderInfo(StringUtil.generateShortId(),0,shopUserId,0,shopId,userId);
        int insert = orderInfoMapper.insert(orderInfo);
        return insert < 1;
    }

    @Override
    public boolean deleteOrder(Long orderId, String userId) {
        int delete = orderInfoMapper.update(null,
                new UpdateWrapper<OrderInfo>()
                        .eq("order_id", orderId)
                        .eq("user_id", userId)
                        .set("del_flag", 1));
        return delete < 1;
    }

    @Override
    public boolean invalidOrder(String orderId) {
        int insert = orderInfoMapper.update(null, new UpdateWrapper<OrderInfo>()
                                                        .eq("order_id", orderId)
                                                        .set("order_status", 1));
        return insert < 1;
    }

    @Override
    public boolean specialDataPay(String userId, Integer count, String sendEmail, HttpServletRequest request) {
        return false;
    }

    private List<OrderListFinalVO> getResult(List<OrderListVO> orderList){
        // 结果集合
        List<OrderListFinalVO> result = new ArrayList<>();
        long count = orderList.stream()
                .parallel()
                .filter(Objects::nonNull)
                .peek(orderListVO -> {
                    // 从每一个订单数据中获取标签id从而得到标签集合数据
                    String tagList = orderListVO.getTagList();
                    if (tagList == null || "".equals(tagList)) {
                        // 标签可为空还有啥好说的，直接返回
                        result.add(new OrderListFinalVO(orderListVO, null));
                        return;
                    }
                    List<TagVO> tagInfos = tagUtil.getTagList(tagList);
                    result.add(new OrderListFinalVO(orderListVO, tagInfos));
                }).count();
        return result;
    }


    /*@Override
    @Transactional(rollbackFor = Exception.class)
    public boolean specialDataPay(String userId, Integer count, String sendEmail, HttpServletRequest request) {
        try {
            // 从redis中找到他刚才选择的数据
            List<String> cardInfoListString = redisUtil.getListFromRedis(userId + Constants.SPECIAL_PAY_SUFFIX);
            if (cardInfoListString == null || cardInfoListString.size() == 0) {
                return false;
            }
            ObjectMapper mapper = new ObjectMapper();
            List<CardInfo> cardInfoList = cardInfoListString.stream()
                    .parallel()
                    .map(cardInfo -> {
                        try {
                            return mapper.readValue(cardInfo, CardInfo.class);
                        } catch (JsonProcessingException e) {
                            throw new RuntimeException(e);
                        }
                    })
                    .collect(Collectors.toList());
            // 需要打印的字段
            List<String> includeColumnFiledNames = new ArrayList<>();
            CardInfo cardInfo = cardInfoList.get(0);
            Class<?> clazz = cardInfo.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                String fieldName = field.getName();
                Object fieldValue;
                try {
                    fieldValue = field.get(cardInfo);
                    if (fieldValue != null && !"".equals(fieldValue)){
                        includeColumnFiledNames.add(fieldName);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            // 去除第一个serialVersionUID属性
            includeColumnFiledNames.remove(0);
            // 购买需要的积分
            BigDecimal needPoint = Constants.SPECIAL_TAG_PRICE.multiply(BigDecimal.valueOf((long) includeColumnFiledNames.size() * count));
            // 插入订单数据
            String orderId = StringUtil.generateShortId();
            // 订单购买的商品的详细信息
            String msg = "购买自定义的数据（包含" + String.join(",", includeColumnFiledNames) + "字段) 共" + count + "条，请到邮箱中查看数据";
            SpecialOrder specialOrder = new SpecialOrder(null, orderId, needPoint, null, null, userId, null, msg);
            int insert = specialOrderMapper.insert(specialOrder);
            if (insert < 1) {
                throw new RuntimeException();
            }
            // 修改账户数据
            BigDecimal originPointBalance = updateAccountData(userId, needPoint);
            // 记录购买日志数据
            saveRfCommonPayLog(userId, orderId, needPoint, originPointBalance, request);
            File destinationDir = new File(Constants.EXCEL_PATH);
            if (!destinationDir.exists()) {
                boolean mkdirs = destinationDir.mkdirs();
                if (!mkdirs){throw new BusinessException(GET_DATA_FALSE);}
            }
            // 获取绝对路径
            String absolution = destinationDir.getAbsolutePath() + File.separator + specialOrder.getOrderId() + ".xlsx";
            // 生成一个excel文档存放到目标文件夹中
            ExcelUtil.saveDataToExcel(cardInfoList, absolution, SHEET
                    , ExcelTypeEnum.XLSX, CardInfo.class, includeColumnFiledNames);
            // 配置邮件发送的相关数据
            SendVO sendVO = new SendVO(EmailConstants.EMAIL_SMTP, EmailConstants.EMAIL_USERNAME, sendEmail, EmailConstants.EMAIL_KEY);
            EmailVO emailVO = new EmailVO(EmailConstants.TITLE, EmailConstants.TITLE_ENCODER, EmailConstants.TEXT
                    , EmailConstants.TEXT_ENCODER, EmailConstants.ATTACH_NAME, absolution);
            // 发送邮件
            PostEmailUtil.sendMailAndAttach(sendVO, emailVO);
            return true;
        } catch (RuntimeException e) {
            throw new RuntimeException(e);
        }
    }*/

    /**
     * 记录订单日志
     */
    public int saveRfCommonPayLog(String userId, String shopId, BigDecimal needPoint, BigDecimal pointBalance, HttpServletRequest request){
        // 记录订单日志
        RfCommonPayLog rfCommonPayLog = new RfCommonPayLog(null, userId, APP_PHONE, shopId, ORDER_BODY, 1
                , needPoint, pointBalance, pointBalance.subtract(needPoint), 1,
                TRADE_TYPE, null, request.getRemoteAddr(), null, null, null);
        return rfCommonPayLogMapper.insert(rfCommonPayLog);
    }

    /**
     * 修改账户余额
     */
    public BigDecimal updateAccountData(String userId, BigDecimal needPoint){
        // 查询用户账户余额
        BigDecimal pointBalance = accountInfoMapper.selectPointBalance(userId);
        if (pointBalance.compareTo(needPoint) < 0){
            // 余额不足直接终止操作
            throw new BusinessException("余额不足");
        }
        // 扣减余额
        int update = accountInfoMapper.updatePoint(userId, pointBalance.subtract(needPoint));
        if (update < 1){throw new BusinessException(FALSE_PAY);}
        // 返回修改前的余额
        return pointBalance;
    }

    @Override
    public List<SpecialOrderVO> getSpecialOrderList(String userId) {
        return specialOrderMapper.getSpecialOrderList(userId);
    }

    @Override
    public boolean deleteSpecialOrder(String userId, Long orderId) {
        int update = specialOrderMapper.update(null,
                new UpdateWrapper<SpecialOrder>()
                        .eq("user_id", userId)
                        .eq("order_id", orderId)
                        .set("del_flag", 1));
        return update > 0;
    }

    /**
     * 请求支付授权，创建order。返回orderId
     * @param paymentVO
     * @return
     */
    @Override
    public String approve(String userId,PaymentVO paymentVO) {

            // 生成订单
            OrderInfo orderInfo = new OrderInfo();
            orderInfo.setOrderId(StringUtil.generateShortId());
            orderInfo.setShopId(paymentVO.getShopId());
            orderInfo.setUserId(userId);
            orderInfo.setShopUserId(paymentVO.getShopUserId());
            orderInfo.setAmount(paymentVO.getAmount());
            return orderInfo.getOrderId();

    }
    /**
     * 前端支付完成,余额支付直接调用此方法
     */
    @Override
    public ResponseVO complete(CompleteVO completeVO) {


        //余额支付
        String orderId = completeVO.getOrderId();
        String lockName = "access:lock:complete:" + orderId;
        String lockId = String.valueOf(UUID.randomUUID());
//        if (!RedisLockUtil.tryLock(lockName, lockId, 20L)) {
//            // 调用太快
//            return new ResponseVO(PaymentEnum.getStatusByCode(4),4,PaymentEnum.getMsgByCode(4));
//        }
        // 获取订单信息
        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>()
                .eq("order_id", orderId));

        if ((orderInfo.getOrderStatus() != 0)) {
            // 订单不是待支付状态
            return new ResponseVO(PaymentEnum.getStatusByCode(2),2,PaymentEnum.getMsgByCode(2));
        }
        String uid = orderInfo.getUserId();
        // TODO 双数据库问题
        AccountInfo accountInfo = accountInfoMapper.selectAccountInfoByUid(uid);


        if (accountInfo.getAvailableBalance().compareTo(orderInfo.getAmount()) < 0) {
            // 余额不足，请前往充值
            return new ResponseVO(PaymentEnum.getStatusByCode(5),5,PaymentEnum.getMsgByCode(5));
        }
        BigDecimal newPointBalance = accountInfo.getPointBalance().subtract(orderInfo.getAmount());
        BigDecimal newAvailableBalance = accountInfo.getAvailableBalance().subtract(orderInfo.getAmount());
        int update = orderInfoMapper.update(null,new UpdateWrapper<OrderInfo>()
                                                            .eq("order_id",orderId)
                                                            .set("order_status",1));

        update += accountInfoMapper.update(null, new UpdateWrapper<AccountInfo>()
                                                                .eq("uid", uid)
                                                                .set("point_balance", newPointBalance)
                                                                .set("available_balance",newAvailableBalance));
        if (update < 2){
            return new ResponseVO(PaymentEnum.getStatusByCode(7),7,PaymentEnum.getMsgByCode(7));
        }
        //更新好友列表
        updateFriends(orderId);
        // 支付成功
        return new ResponseVO(PaymentEnum.getStatusByCode(6),200,PaymentEnum.getMsgByCode(6));


    }

    private void updateFriends(String orderId){
        //根据订单id查询对应卡片的用户ids和当前用户id
        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>()
                .eq("order_id", orderId));
        List<OrderCard> orderCards = orderCardMapper.selectList(new QueryWrapper<OrderCard>()
                .eq("order_id", orderInfo.getOrderId()));
        List<String> userIds = orderCards
                .stream()
                .parallel()
                .map(OrderCard -> {
                    CardInfo cardInfo = cardInfoMapper.selectOne(new QueryWrapper<CardInfo>()
                            .eq("card_id", OrderCard.getCardId()));
                    return cardInfo.getUserId();
                })
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        String userId = orderInfo.getUserId();
        //更新当前用户和对应卡片用户的好友列表
        //更新当前用户好友列表
        String cards = cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>()
                .eq("user_id", userId)).getCardList();
        if(!cards.isEmpty()){
            JSONArray jsonArray = JSON.parseArray(cards);
            List<String> cardList = JSON.parseArray(jsonArray.toJSONString(), String.class);
            cardList.addAll(userIds);
            cardOrderInfoMapper.update(null, new UpdateWrapper<CardOrderInfo>()
                    .eq("user_id", userId)
                    .set("card_list", JSON.toJSONString(cardList)));
        }
        //更新对应卡片用户好友列表
        for (String id : userIds) {
            CardOrderInfo cardOrderInfo = cardOrderInfoMapper.selectOne(new QueryWrapper<CardOrderInfo>()
                    .eq("user_id", id));
            if (cardOrderInfo != null){
                String cards2 = cardOrderInfo.getCardList();
                if (!cards2.isEmpty()){
                    JSONArray jsonArray2 = JSON.parseArray(cards2);
                    List<String> cardList2 = JSON.parseArray(jsonArray2.toJSONString(), String.class);
                    cardList2.add(userId);
                    cardOrderInfoMapper.update(null, new UpdateWrapper<CardOrderInfo>()
                            .eq("user_id", userId)
                            .set("card_list", JSON.toJSONString(cardList2)));
                }
            }

        }
    }

    @Override
    public Boolean cancelled(String orderId) {
        int update = orderInfoMapper.update(null, new UpdateWrapper<OrderInfo>()
                .eq("order_id", orderId)
                .set("order_status", 3));
        return update > 0;
    }

    @Override
    public String createOrder(String userId, OrderDTO orderDTO) {
        // 生成订单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderId(StringUtil.generateShortId());
        orderInfo.setUserId(userId);
        orderInfo.setAmount(orderDTO.getAmount());

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, 30);
        Date newDate = calendar.getTime();
        orderInfo.setInvalidTime(newDate);


        orderInfoMapper.insert(orderInfo);
        for (String cardId : orderDTO.getCardIds()) {
            OrderCard orderCard = new OrderCard(null, orderInfo.getOrderId(), cardId);
            orderCardMapper.insert(orderCard);
        }
        return orderInfo.getOrderId();
    }

    @Override
    public OrderDetailsVO getPayOrderDetailsList(String userId, String orderId) {
        OrderDetailsVO orderDetailsVO = new OrderDetailsVO();
        OrderInfo orderInfo = orderInfoMapper.selectOne(new QueryWrapper<OrderInfo>()
                .eq("user_id", userId)
                .eq("order_id",orderId));
        BeanUtil.copyProperties(orderInfo, orderDetailsVO);
        List<OrderCard> orderCards = orderCardMapper.selectList(new QueryWrapper<OrderCard>()
                .eq("order_id", orderId));
        List<CardAllInfoVO> cardAllInfoVOs = orderCards.stream().map(orderCard -> {
            CardAllInfoVO cardAllInfoVO = new CardAllInfoVO();
            CardInfo cardInfo = cardInfoMapper.selectOne(new QueryWrapper<CardInfo>()
                    .eq("card_id", orderCard.getCardId()));
            cardAllInfoVO.setCardInfo(cardInfo);
            if (cardInfo != null) {
                JSONArray jsonArray = JSON.parseArray(cardInfo.getTagList());
                List<TagVO> TagVOs = JSON.parseArray(jsonArray.toJSONString(), String.class)
                        .stream()
                        .map(id -> {
                            tagInfoMapper.selectById(id);
                            TagVO tagVO = new TagVO();
                            BeanUtil.copyProperties(tagInfoMapper.selectById(id), tagVO);
                            return tagVO;
                        })
                        .collect(Collectors.toList());
                cardAllInfoVO.setTagVOList(TagVOs);
            }
            return cardAllInfoVO;
        }).collect(Collectors.toList());
        orderDetailsVO.setCardAllInfoVOs(cardAllInfoVOs);
        return orderDetailsVO;
    }
}


